DialogHandler v1.1
(c) 2001 Aleksandar Stancic (astancic@EUnet.yu)
===============================================

Hi all!

'Dialog Handler' can handle 30 DIALOGS at the same time,
and within each dialog about 20 TABs.

;********************************************************************************
'Dialog Handler' will...

1. track position of the dialog.
2. add tooltips to controls.
3. add tabs to TAB CONTROLS and processes TCN_SELCHANGE message.
4. simplify dialog messages processing:

   A classic dialog handler may look something like this:
;================================================================================
	DlgHandler proc uses ebx esi edi, hwndDlg, uMsg, wParam, lParam

		.if [uMsg]==WM_INITDIALOG
			;initialize controls

			;add tabs to tab control, (and, later, handle tab activation)
			;add tooltips
			;set dialog position

		.elseif [uMsg]==WM_COMMAND && word ptr [wParam+2]==BN_CLICKED
			.if word ptr [wParam]==IDCANCEL
				;remember dialog position
				call	EndDialog, [hwndDlg], null
			.else
				jmp	@@NotHandled
			.endif

		.elseif [uMsg]==blah, blah, blah...

		.else
	@@NotHandled:	mov	eax,false
			jmp	@@Ret
		.endif
			mov	eax,true
	@@Ret:		ret
	DlgHandler endp
;================================================================================
   With 'Dialog Handler' it looks like this:

	InitDialog proc
			;initialize controls
			ret
	InitDialog endp

	IDCANCEL__BN_CLICKED proc
			call	EndDialog, ebx, null
			ret
	IDCANCEL__BN_CLICKED endp

   Before CALLing your PROC, 'Dialog Handler' will setup registers as follows:
	ebx = dialog handle
	edi = lParam value
	edx = points at the DlgMsg structure (see below)
   Inside every PROC you can use all regs (eax,ebx,ecx,edx,esi,edi,ebp)
;********************************************************************************


;********************************************************************************
How to use it?
;********************************************************************************

(first of all, 'hInstance' must be made PUBLIC)

To use 'Dialog Handler', you call one of the *Param functions.
	Example:
		call	DialogBoxParam, [hInstance], IDD_????, [hWndParent], \
			offset DialogHandler, offset DlgHeder_????

"DlgHeder_????" is a pointer to a "DlgHeder" structure defined as follows:
	DlgHeder struc
	  DH_pXY	dd  0 ;points at Dialog position (two WORDS)	(null = don't save POS.)
	  DH_pTab	dd  0 ;points at TAB control information	(null = no TAB in dialog)
	  DH_pTips	dd  0 ;points at ToolTip information		(null = no TIPS in dialog)
	  DH_TipsEnable	dd  0 ;points at global ToolTip enable byte	(null = always tip)
	  DH_hTip	dd  ? ;returned ToolTip handle (after creation)
	DlgHeder ends

IMMEDIATELY after the "DlgHeder" structure, you MUST place "DlgMsg" structure(s):
	DlgMsg struc
	  DM_uMsg	dd  0 ;Message value (WM_INITDIALOG, WM_COMMAND..) (null = Table End)
	  DM_wParam	dd  0 ;value of wParam ("DontCare" is avaiable)
	  DM_Handler	dd  0 ;points at handler PROC
	DlgMsg ends
  (as you can see, lParam is not used; so far, that is not a problem)

	    "DlgHeder" and "DlgMsg" are two structures that
	you MUST use for EVERY dialog handled by 'Dialog Handler'.
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	NOTE:
	"dwInitParam" parameter can be null, but then:
		1. you will not receive any messages
		2. dialog position && tips && tabs won't be handled
		3. dialog will be closed when WM_COMMAND && (IDOK || IDCANCEL) is received
	(Of course, if "dwInitParam" is null, "DlgHeder" and "DlgMsg" are not necessary)
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Then, there are five additional data 'structures' - all optional:

1. Global ToolTip enable:
	db	true/false	(true = create ToolTips; false = don't create ToolTips)
   This byte enables/disables ToolTip creation (can be used globally)

2. Dialog position:
	dw	X,Y
   'DialogHandler' uses these two words at:
	1. WM_INITDIALOG: to set last dialog position
	2. WM_NCDESTROY:  to remember current dialog position for future use

3. ToolTip information:
	DlgTips	Label	;define start of ToolTips information
		DlgTip ControlID_1,	'ToolTip text 1'
		DlgTip ControlID_2,	'ToolTip text 2'
		.
		.
		DlgTip null	;end marker

4. TAB control information:
	TabInfo	Label	;define start of TAB information
		NewTab	tab_ID_1, CurrentlySelectedTAB	;select first tab CONTROL
			AddTab	DialogID_1,	DlgHeder_1,	'tab text 1'	;insert tab in first control
			AddTab	DialogID_2,	DlgHeder_2,	'tab text 2'
			AddTab	DialogID_3,	DlgHeder_3,	'tab text 3'

		NewTab	tab_ID_2		;select second tab CONTROL
			AddTab	DialogID_4,	DlgHeder_4,	'tab text 4'	;insert tab in second control
			AddTab	DialogID_5,	DlgHeder_5,	'tab text 5'
			AddTab	DialogID_6,	DlgHeder_6,	'tab text 6'
		.
		.
		NewTab	null	;end marker

   'NewTab' macro will create a TabData structure:
	TabData struc
	  TD_flag	dd  1 ;flag: new tab (ie. it's not "NewTab null")
	  TD_id		dd  ? ;TAB_id (resource ID of the TAB CONTROL)
	  TD_SelTab	dd  0 ;points at Currently Selected TAB
	  TD_hTab	dd  ? ;returned TAB handle (after creation)
	TabData ends

	NOTE:
		If "TD_SelTab" is null, 'Dialog Handler' uses "TD_SelTab" itself to
		remember last selected tab. This works until the APP is terminated.

5. CurrentlySelectedTAB
	db	Tab2Select ;(zero index of the tab to select)
   'DialogHandler' uses this byte at:
	1. WM_INITDIALOG: to select last active tab
	2. TCN_SELCHANGE: to remember current tab selected for future use

;================================================================================
Thats it. I hope all this works... It's been tested od Win95 OSR2.
